package org.example.loadbalancer;

import org.example.model.ServiceMetaInfo;

import java.util.TreeMap;
import java.util.List;
import java.util.Map;

/**
 * @Title: ConsistentHashLoadBalancer
 * @Author: kunliangzhao
 * @Package org.example.loadbalancer
 * @Date: 2025/6/23 14:55
 * @Description: 一致性哈希负载均衡器
 */
public class ConsistentHashLoadBalancer implements LoadBalancer{
    /**
     * 一致性Hash环，存放虚拟节点
     */
    private final TreeMap<Integer, ServiceMetaInfo> virtuaNodes = new TreeMap<>();

    /**
     * 虚拟节点数
     */
    private static final int VIRTUAL_NODE_NUM = 10;

    @Override
    public ServiceMetaInfo select(Map<String, Object> requestParams, List<ServiceMetaInfo> serviceMetaInfoList) {
        if (serviceMetaInfoList.isEmpty())
            return null;

        // 构建虚拟节点环
        for (ServiceMetaInfo serviceMetaInfo : serviceMetaInfoList) {
            for (int i = 0; i < VIRTUAL_NODE_NUM; i++) {
                String virtualNodeName = serviceMetaInfo.getServiceAddress() + "#" + i;
                int hash = getHash(virtualNodeName);
                virtuaNodes.put(hash, serviceMetaInfo);
            }
        }

        // 获取调用请求的hash值
        int hash = getHash(requestParams);

        // 选择最接近且大于等于请求hash值的虚拟节点
        Map.Entry<Integer, ServiceMetaInfo> entry = virtuaNodes.ceilingEntry(hash);
        if(entry == null){
            // 如果没有节点大于等于请求hash值，则选择第一个节点
            entry = virtuaNodes.firstEntry();
        }
        return entry.getValue();
    }

    private int getHash(Object key){
        return key.hashCode();
    }
}
